﻿// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. 
// See License.txt in the project root for license information.
using System;
using System.Cloud.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ListOfLists_WPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Dictionary<string, ObservableCloudList<ListItem>> m_listNameMapping = new Dictionary<string, ObservableCloudList<ListItem>>();
        private ObservableCloudList<string> m_listNameCollection;

        internal static ListBox dragSource = null;

        // Use these to connect to cloud (production) azure cluster
        //internal static string s_connectionString = "<yourcloudcluster>.cloudapp.net:19000";
        //internal static bool s_useGateway = true;

        // Use these to connect to local (development) azure cluster
        internal static string s_connectionString = "127.0.0.1:19000";
        internal static bool s_useGateway = false;

        public MainWindow()
        {
            InitializeComponent();
            InitializeAsync(); // fire-and-forget
        }

        private async void InitializeAsync()
        {
            m_listNameCollection = await CreateCloudListAsync<string>("mainList");
            foreach (string name in m_listNameCollection)
                await CreateLocalListAsync(name);
            m_listNameCollection.CollectionChanged += m_listNameCollection_CollectionChanged;
        }

        async void m_listNameCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
            {
                foreach (var item in e.NewItems)
                {
                    var name = (string)item;
                    if (!m_listNameMapping.ContainsKey(name))
                    {
                        await CreateLocalListAsync(name);
                    }
                }
            }
            else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
            {
                foreach (var item in e.OldItems)
                {
                    var name = (string)item;
                    if (m_listNameMapping.ContainsKey(name))
                    {
                        DeleteLocalList(name);
                    }
                }

            }

            //throw new NotImplementedException();
        }

        private async Task<ObservableCloudList<T>> CreateCloudListAsync<T>(string listName)
        {
            var sc = SynchronizationContext.Current;
            var listCreator = Task.Factory.StartNew(() =>
                {
                    return new ObservableCloudList<T>(s_connectionString, "demo_" + listName, sc, s_useGateway);
                });
            return await listCreator;
        }

        private async Task CreateLocalListAsync(string listName)
        {
            var newList = await CreateCloudListAsync<ListItem>(listName);
            var newControl = new InnerListControl(listName, newList);
            newControl.Margin = new Thickness(5, 5, 5, 5);
            m_listNameMapping.Add(listName, newList);
            this.stackPanelMain.Children.Add(newControl);
        }

        private void DeleteLocalList(string listName)
        {
            // Remove the control associated with the list from the panel
            InnerListControl foundItem = null;
            foreach (var control in stackPanelMain.Children)
            {
                if (((InnerListControl)control).ListName.Equals(listName))
                {
                    foundItem = (InnerListControl)control;
                    break;
                }
            }
            if (foundItem != null) stackPanelMain.Children.Remove(foundItem);

            // Unmark the list as existent
            if (m_listNameMapping.ContainsKey(listName))
            {
                m_listNameMapping.Remove(listName);
            }
        }

        async void OnAddList(object sender, RoutedEventArgs e)
        {
            var dlg = new ListNameDialog();
            dlg.ShowDialog();
            if (dlg.ListName == null) return;

            await CreateLocalListAsync(dlg.ListName);
            m_listNameCollection.Add(dlg.ListName);
        }

    }

    [Serializable]
    public class ListItem
    {
        public ListItem()
        {
            CreationTime = DateTime.UtcNow;
            UpdateTime = DateTime.UtcNow;
        }

        public string Description { get; set; }
        public DateTime CreationTime { get; set; }
        public DateTime UpdateTime { get; set; }
        public string Color { get; set; }

        public override bool Equals(object obj)
        {
            var other = obj as ListItem;
            return (other != null) && other.Description.Equals(Description); // "Description" field is only factor in equality
        }

        public override int GetHashCode()
        {
            return Description.GetHashCode();
        }


    }
}
